#include "extendedtimingparser.h"

int ExtendedTimingParser :: readTimingFile(){
        
        bool valid = false ;
        do {
                string pinName;
                LibPinTimingInfo* LPTI = new LibPinTimingInfo;
                
                valid = (*this).read_pin_timing (LPTI->cellInst, LPTI->pin, LPTI->riseSlack, LPTI->fallSlack,
                                                 LPTI->riseTransition, LPTI->fallTransition) ;
                
                if (valid) {
                        //std::cout << "Timing for pin: " << LPTI->cellInst << "/" << LPTI->pin << ": "
                        //<< LPTI->riseSlack << " " << LPTI->fallSlack << " "
                        //<< LPTI->riseTransition << " " << LPTI->fallTransition << endl ;
                        
                        pinName = "";
                        pinName = LPTI->cellInst + "/" + LPTI->pin;
                        this->PinsTiming.insert(std::pair<std::string, LibPinTimingInfo>(pinName, *LPTI));
                }
                
        } while (valid) ;
  

        do {
                
                LibPortTimingInfo *LPTI = new LibPortTimingInfo;
                
                valid = (*this).read_port_timing (LPTI->port, LPTI->riseSlack, LPTI->fallSlack,
                                             LPTI->riseTransition, LPTI->fallTransition) ;

                if (valid) {
                        //std::cout << "Timing for port: " << LPTI->port << ": " << LPTI->riseSlack << " " << LPTI->fallSlack << " "
                        //<< LPTI->riseTransition << " " << LPTI->fallTransition << endl ;
                        
                        this->PortsTiming.insert(std::pair<std::string,LibPortTimingInfo>(LPTI->port, *LPTI));
                }
                                
        } while (valid) ;
        
        this->closeTimingFile();
        //cout<<"Pin Size is "<< (*this).PinsTiming.size()<<endl;
        //cout<<"Port Size is "<< (*this).PortsTiming.size()<<endl;
        
        return 0;
}
/*
int ExtendedTimingParser :: closeTimingFile(){
        
        is.close();
        return 0;
}
*/

bool ExtendedTimingParser::update_pin_timing (std::ifstream& fi, string& cellInst, string& pin,
                                    double& riseSlack, double& fallSlack,
                                    double& riseTransition, double& fallTransition) {
        string tmp;
        vector<string> tokens ;
        bool valid = read_line_as_tokens (fi, tokens) ;
        
        assert (valid) ;
        assert (tokens.size() >= 2) ;

        if (tokens[0] == "port" && tokens[1] == "timing") {
                // The next section (port timing) will start after this point
                return false ;

        } else {

                assert (tokens.size() == 6) ;
                cellInst = tokens[0] ;
                pin = tokens[1] ;
                tmp = "";
                tmp = cellInst + "/" + pin;
                
                this->PinsTiming[tmp].riseSlack = atof(tokens[2].c_str()) ;
                this->PinsTiming[tmp].fallSlack = atof(tokens[3].c_str()) ;
                this->PinsTiming[tmp].riseTransition = atof(tokens[4].c_str()) ;
                this->PinsTiming[tmp].fallTransition = atof(tokens[5].c_str()) ;

                return true ;
        }
  
}

bool ExtendedTimingParser::update_port_timing (std::ifstream& fi, string& port, double& riseSlack, double& fallSlack,
                                     double& riseTransition, double& fallTransition) {
        
        vector<string> tokens ;
        bool valid = read_line_as_tokens (fi, tokens) ;
        
        if (valid) {
    
                assert (tokens.size() == 5) ;
                port = tokens[0] ;
                
                this->PortsTiming[port].riseSlack = atof(tokens[1].c_str()) ;
                this->PortsTiming[port].fallSlack = atof(tokens[2].c_str()) ;
                this->PortsTiming[port].riseTransition = atof(tokens[3].c_str()) ;
                this->PortsTiming[port].fallTransition = atof(tokens[4].c_str()) ;

        } 

        return valid ;

}

int ExtendedTimingParser :: updateTimingFile(string filename){
        
        std::ifstream fi(filename.c_str());
        
        // Skip the first comment in the file
        vector<string> tokens ;
        bool valid = read_line_as_tokens (fi, tokens) ;
        
        assert (valid) ;
        assert (tokens.size() == 2) ;
        assert (tokens[0] == "pin" && tokens[1] == "timing") ;
        
        valid = false ;
        do {
                LibPinTimingInfo* LPTI = new LibPinTimingInfo;
                
                valid = (*this).update_pin_timing (fi,LPTI->cellInst, LPTI->pin, LPTI->riseSlack, LPTI->fallSlack,
                                                   LPTI->riseTransition, LPTI->fallTransition) ;
                
                
        } while (valid) ;
  

        do {
                
                LibPortTimingInfo *LPTI = new LibPortTimingInfo;
                
                valid = (*this).update_port_timing (fi,LPTI->port, LPTI->riseSlack, LPTI->fallSlack,
                                             LPTI->riseTransition, LPTI->fallTransition) ;
                
        } while (valid) ;
        
        fi.close();
        return 0;
}
